package org.my.spring.agent.app.service;

import cn.hutool.http.HtmlUtil;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.my.spring.agent.common.domain.Result;
import org.my.spring.agent.mcp.core.config.AgentMcpConfig;
import org.my.spring.agent.mcp.core.domain.dto.IntentResult;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.messages.Message;
import org.springframework.ai.chat.messages.SystemMessage;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;

import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 智能代理路由服务
 * 负责意图识别、任务路由和结果处理的核心服务类
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class AgentRouterService {
    private final ChatClient chatClient;
    private final AgentMcpConfig agentMcpConfig;
    private final AgentMcpService mcpService;
    /**
     * 意图识别提示词模板
     * 用于指导AI模型进行任务分类、步骤拆解和指令生成
     * 包含输出格式定义和决策逻辑
     */
    private static final String INTENT_PROMPT = """
                你作为「任务分类MCP编排专家」，请严格按以下规则处理用户输入：
                1. **分类**：基于文本分析识别任务类型 → `Web自动化` 或 `其他`
                2. **拆解**：生成3-5个顺序执行步骤，每个步骤必须是原子操作
                3. **指令**：每个步骤包含可直接执行的MCP命令
                4. **输出**：纯净JSON格式
                        
                ### 核心能力
                1. 文本分析 → 识别任务关键特征
                2. 分类决策树：
                   - 包含「网页/浏览器/数据抓取/表单填写」等关键词 → Web自动化
                   - 不匹配上述特征 → 其他
                3. 步骤生成：
                   - Web自动化：使用浏览器操作指令
                   - 其他：使用通用操作指令
                ### MCP上下文：%s 
                   - 请基于上下文(JSON格式)回答用户问题，如果上下文为空或不相关则忽略。      
                ### 输出格式
                ```json
                    {
                      "userId": "用户id",
                      "input": "用户输入原文",
                      "type": "分类结果",  // "Web自动化" 或 "其他"
                      "answer": "将最终的回答放在这里",
                      "steps": [
                        {
                          "stepId": "STEP_1",  // 格式：STEP_{序号}
                          "description": "步骤说明",
                          "command": {
                            "action": "操作指令",//clickElement:点击元素、inputText:输入关键字、navigate:跳转网址、outputStr:输出结果
                            "url":"网址",
                            "inputId":"网页元素ID",//必须包含该字段，没有留空
                            "inputName":"网页元素名称",//必须包含该字段，没有留空
                            "inputValue":"元素值"//必须包含该字段，没有留空
                          }
                        }
                      ]
                    }
                ```
            """;


    /**
     * 路由并执行用户请求
     * @param jsonObject 包含用户输入和用户ID的请求参数
     * @return 包含执行结果的Result对象
     * @throws IllegalArgumentException 如果用户输入或用户ID为空
     */
    public Result<?> routeAndExecute(JSONObject jsonObject) {
        String userInput = jsonObject.getString("message");
        String userId = jsonObject.getString("userId");
        if (StringUtils.isBlank(userInput) || StringUtils.isBlank(userId)) {
            return Result.error("参数错误");
        }
        // 步骤1: 意图识别
        IntentResult intent = detectIntent(userInput);
        // 步骤2: 路由到对应智能体
        Optional<AgentMcpConfig.McpInfo> mcpInfo = agentMcpConfig.getTools().stream()
                .filter(tool -> tool.enable() && tool.name().equals(intent.type()))
                .findFirst();
        return mcpInfo.map(info -> Result.success(defaultAnswer(userInput, mcpService.callTool(info, intent), true)))
                .orElseGet(() -> Result.success(defaultAnswer(userInput, "", false)));
    }

    /**
     * 识别用户输入意图
     * 通过调用AI模型分析用户输入，生成任务分类和执行步骤
     * @param userInput 用户输入文本
     * @return 包含意图分类和执行步骤的IntentResult对象
     */
    private IntentResult detectIntent(String userInput) {
        // 调用DeepSeek
        String jsonResponse = chatClient.prompt(INTENT_PROMPT).user(userInput).call().content();
        log.debug("jsonResponse-old:{}", jsonResponse);
        jsonResponse = jsonResponse.replaceAll("```json", "").replaceAll("```", "").trim();
        log.debug("jsonResponse-new:{}", jsonResponse);
        return JSON.parseObject(jsonResponse, IntentResult.class);
    }

    /**
     * 生成默认回答
     * 根据用户输入和工具执行结果生成最终回答
     * @param userInput 用户输入文本
     * @param context 工具执行结果上下文
     * @param hasTool 是否使用了工具
     * @return 格式化的回答字符串
     */
    private String defaultAnswer(String userInput, String context, boolean hasTool) {
        log.info("默认回答：{}", userInput);
        String result = chatClient
                .prompt(buildPrompt(userInput, context))
                .call()
                .content();
        log.debug("最终回答：{}", result);
        String jsonResponse = result.substring(result.indexOf("```json") + 7, result.lastIndexOf("```")).trim();
        String otherMsg = result.substring(result.lastIndexOf("```") + 3).trim();
        log.debug("jsonResponse-new:{} otherMsg:{}", jsonResponse, otherMsg);
        IntentResult intentResult = JSON.parseObject(jsonResponse, IntentResult.class);
        if (!hasTool || ObjectUtils.isEmpty(intentResult.steps())) {
            return intentResult.answer();
        }
        String plan = intentResult.steps().stream()
                .map(step -> step.stepId() + ": " + step.description())
                .collect(Collectors.joining("<br>"));

        return "### 智能助手已生成执行计划：<br>" + plan + "<br>### 智能助手执行计划结果：<br>" + context + "<br>### " + otherMsg;
    }

    /**
     * 构建AI模型提示
     * 组合系统消息和用户消息，生成完整的提示内容
     * @param userInput 用户输入文本
     * @param context 上下文信息
     * @return 构建好的Prompt对象
     */
    private Prompt buildPrompt(String userInput, String context) {
        // 1. 构建系统消息（包含MCP上下文）
        String systemText = String.format(INTENT_PROMPT, HtmlUtil.cleanHtmlTag(context));
        Message systemMessage = new SystemMessage(systemText);
        // 2. 用户消息
        Message userMessage = new UserMessage(userInput);
        // 3. 组合成最终提示
        return new Prompt(List.of(systemMessage, userMessage));
    }
}
